<script lang="ts" setup>
import { getTokenHeader } from '@/utils/auth'
import type { UploadProps } from 'element-plus'
import { useFormDisabled, useFormItem } from 'element-plus'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

NProgress.configure({ showSpinner: false })

const isDisabled = useFormDisabled()
const { formItem } = useFormItem()
const modelValue = defineModel<string>({ required: true })
const props = withDefaults(
  defineProps<{
    action?: string
    headers?: { [x: string]: string }
    srcPath?: string
    limit?: number
    size?: number
    disabled?: boolean
    types?: string[]
    withCredentials?: boolean
    width?: string
    height?: string
    hasLoading?: boolean
    onSuccess?: UploadProps['onSuccess']
    beforeUpload?: UploadProps['beforeUpload']
    onProgress?: UploadProps['onProgress']
  }>(),
  {
    action: import.meta.env.VITE_APP_UPLOAD_URL as string,
    headers: () => getTokenHeader(),
    srcPath: 'object.url',
    limit: 1,
    size: 10,
    disabled: false,
    types: () => ['gif', 'jpg', 'jpeg', 'png'],
    withCredentials: true,
    width: '200',
    height: '200',
    hasLoading: true
  }
)

const styles = computed(() => {
  return { width: props.width + 'px', height: props.height + 'px' }
})

const handleBeforeUpload: UploadProps['beforeUpload'] = (file) => {
  props.beforeUpload && props.beforeUpload(file)
  return new Promise((resolve, reject) => {
    const type = (file.name.split('.').pop() || '').toLowerCase()
    if (!props.types.includes(type)) {
      ElMessage.error(`暂不支持该格式`)
      return reject(false)
    } else if (file.size > props.size * 1024 * 1024) {
      ElMessage.error(`上传文件不能超过${props.size}M`)
      return reject(false)
    } else {
      return resolve(true)
    }
  })
}

// 附件上传之前
const handelProgress: UploadProps['onProgress'] = (event, file, fileList) => {
  props.hasLoading && NProgress.start()
  props.onProgress && props.onProgress(event, file, fileList)
}

// 附件件上传成功
const handleSuccess: UploadProps['onSuccess'] = (res, file, fileList) => {
  props.hasLoading && NProgress.done()
  if (props.limit > 1) {
    console.warn('如果上传多个附件,请绑定一个数组！')
    return
  }
  let url = res
  props.srcPath.split('.')?.forEach((item) => {
    url = url?.[item] || ''
  })
  if (res.retCode === '000000' && url) {
    fileList[fileList.length - 1].url = url
    modelValue.value = url
    formItem?.validate('change')
  } else {
    fileList.pop()
  }
  props.onSuccess && props.onSuccess(res, file, fileList)
}
</script>

<template>
  <el-upload
    class="one-upload-image"
    :style="styles"
    :action="action"
    :headers="headers"
    :show-file-list="false"
    :disabled="isDisabled"
    :on-progress="handelProgress"
    :on-success="handleSuccess"
    :before-upload="handleBeforeUpload">
    <img v-if="modelValue" :src="modelValue" style="height: 100%; width: 100%" />
    <div v-else>
      <el-icon size="32"><Plus /></el-icon>
    </div>
  </el-upload>
</template>

<style scoped lang="scss">
.one-upload-image {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  :deep() {
    .el-upload {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .el-upload-dragger {
      width: 100%;
      height: 100%;
    }
  }
}
</style>
